#pragma once
#include <iostream>
#include <functional>
#include <unistd.h>
#include "TcpServer.hpp"

using namespace std;

class Connection;
class TcpServer;

using func_t = function<void(Connection *)>;

class Connection
{
public:
    Connection(int sockfd, uint32_t events, TcpServer *R)
        : _sockfd(sockfd), _events(events), _R(R)
    {
    }

    // 注册连接三个回调处理函数
    void RegisterCallback(func_t reader, func_t writer, func_t excepter)
    {
        _reader = reader;
        _writer = writer;
        _excepter = excepter;
    }

    // 判断输出缓冲区是否为空
    bool OutBufferEmpty()
    {
        return _outbuffer.empty();
    }

    // 向输入缓冲区中追加数据
    void AddInBuffer(string buffer)
    {
        _inbuffer += buffer;
    }

    // 向输出缓冲区中追加数据
    void AddOutBuffer(string buffer)
    {
        _outbuffer += buffer;
    }

    // 获取连接的文件描述符
    int GetSockfd()
    {
        return _sockfd;
    }

    // 获取输入缓冲区的引用
    string& GetInbuffer()
    {
        return _inbuffer;
    }

    // 获取输出缓冲区的引用
    string& GetOutbuffer()
    {
        return _outbuffer;
    }

    // 获取连接对应文件描述符关注事件
    uint32_t GetEvents()
    {
        return _events;
    }

    // 设置连接对应文件描述符关注事件
    void SetEvents(uint32_t events)
    {
        _events = events;
    }

    // 关闭文件描述符
    void Close(int sockfd)
    {
        close(sockfd);
    }

    ~Connection()
    {
    }

private:
    int _sockfd;      // 文件描述符
    uint32_t _events; // 事件

    string _inbuffer;  // 输入缓冲区
    string _outbuffer; // 输入缓冲区

public:
    func_t _reader;   // 读方法
    func_t _writer;   // 写方法
    func_t _excepter; // 异常处理方法

    TcpServer *_R; // 回指指针
};

class ConnectionFactory
{
public:
    // 构建Listen文件描述符的连接
    static Connection *BuildListenConnection(int sockfd, uint32_t events, func_t reader, TcpServer *R)
    {
        Connection *conn = new Connection(sockfd,events,R);
        conn->RegisterCallback(reader, nullptr, nullptr);

        return conn;
    }
    
    // 构建普通文件描述符的连接
    static Connection *BuildNormalConnection(int sockfd, uint32_t events, func_t reader, func_t writer, func_t excepter, TcpServer *R)
    {
        Connection *conn = new Connection(sockfd,events,R);
        conn->RegisterCallback(reader, writer, excepter);

        return conn;
    }
};